package com.mars.boss.weixin.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.mars.base.common.exception.AppException;
import com.mars.base.common.utils.RandomUitl;
import com.mars.base.service.BaseService;
import com.mars.boss.weixin.constant.RedisNamespace;
import com.mars.boss.weixin.entity.WxMenu;
import com.mars.boss.weixin.exception.WxMenuBizException;
import com.mars.boss.weixin.mapper.WxMenuMapper;
import com.mars.boss.weixin.service.WxMenuService;
import com.mars.boss.weixin.vo.Menu;
import com.mars.component.redis.JedisClient;

@Service
public class WxMenuServiceImpl extends BaseService<WxMenu, Long> implements WxMenuService {

	@Autowired
	private WxMenuMapper mapper;

	@Autowired
	private JedisClient jedisClient;

	@Override
	public int insert(WxMenu entity) throws AppException {
		this.clearCache();
		entity.setEventKey(StringUtils.isNotEmpty(entity.getType()) ? entity.getType().toUpperCase() + "_" + RandomUitl.generateString(5).toUpperCase() : null);
		return super.insert(entity);
	}

	@Override
	public int update(WxMenu entity) throws AppException {
		this.clearCache();
		entity.setEventKey(StringUtils.isNotEmpty(entity.getType()) ? entity.getType().toUpperCase() + "_" + RandomUitl.generateString(5).toUpperCase() : null);
		return super.update(entity);
	}

	@Override
	public int deleteByIds(List<Long> idList) throws AppException {
		for (Long id : idList) {
			recursiveDelete(id);
		}
		this.clearCache();
		return 0;
	}

	private void recursiveDelete(Long id) {
		List<WxMenu> loadChildrenNode = this.loadChildrenNode(id);

		if (null != loadChildrenNode) {
			for (WxMenu menu : loadChildrenNode) {
				recursiveDelete(menu.getId());
			}
		}
		super.delete(id);
	}
	
	@Override
	public void status(Long id) {
		WxMenu menu = super.selectById(id) ;
		recursiveDisabled(super.selectById(id), menu.getStatus() == 1 ? 2 : 1);
		this.clearCache();
	}
	
	private void recursiveDisabled(WxMenu entity, int status) {
		entity.setStatus(status);
		
		List<WxMenu> loadChildrenNode = this.loadChildrenNode(entity.getId());
		if (null != loadChildrenNode) {
			status = entity.getStatus() ;
			for (WxMenu menu : loadChildrenNode) {
				recursiveDisabled(menu, status);
			}
		}
		super.updateSelective(entity) ;
	}

	@Override
	public List<WxMenu> selectList(WxMenu entity) throws AppException {
		String menuList = this.jedisClient.get(RedisNamespace.WX_MENU_LIST);
		if (null != menuList) {
			return JSON.parseArray(menuList, WxMenu.class);
		} else {
			List<WxMenu> list = super.selectList(entity);
			this.jedisClient.set(RedisNamespace.WX_MENU_LIST, JSON.toJSONString(list));
			return list;
		}
	}

	@Override
	public List<WxMenu> loadRootNode() throws WxMenuBizException {
		String menuList = this.jedisClient.get(RedisNamespace.WX_MENU_TREE_ROOT);
		if (null != menuList) {
			return JSON.parseArray(menuList, WxMenu.class);
		} else {
			List<WxMenu> list = this.mapper.loadRootNode();
			this.jedisClient.set(RedisNamespace.WX_MENU_TREE_ROOT, JSON.toJSONString(list));
			return list;
		}
	}

	@Override
	public List<WxMenu> loadChildrenNode(Long pid) throws WxMenuBizException {
		return this.mapper.loadChildrenNode(pid);
	}

	@Override
	public List<WxMenu> tree() throws WxMenuBizException {
		List<WxMenu> list = new ArrayList<WxMenu>();

		List<WxMenu> root = this.loadRootNode();
		for (WxMenu menu : root) {
			list.add(recursive(menu));
		}
		return list;
	}

	@Override
	public List<WxMenu> treegrid() throws WxMenuBizException {
		List<WxMenu> list = new ArrayList<WxMenu>();

		List<WxMenu> root = this.loadRootNode();
		for (WxMenu menu : root) {
			list.add(recursive(menu));
		}
		return list;
	}

	private WxMenu recursive(WxMenu menu) {
		String menuJosn = this.jedisClient.getHash(RedisNamespace.WX_MENU_TREE_CHILDREN, "ID_" + menu.getId());
		
		if (null != menuJosn) {
			return JSON.parseObject(menuJosn, WxMenu.class);
		} else {
			List<WxMenu> childs = this.mapper.loadChildrenNode(menu.getId());
			if (null != childs && childs.size() > 0) {
				List<WxMenu> children = new ArrayList<WxMenu>();
				for (WxMenu m : childs) {
					children.add(recursive(m));
				}
				menu.setChildren(children);
			}
			this.jedisClient.setHash(RedisNamespace.WX_MENU_TREE_CHILDREN, "ID_" + menu.getId(), JSON.toJSONString(menu));
			return menu;
		}
	}
	
	@Override
	public List<Menu> getAllMenusToWeixin() {
		List<Menu> list = new ArrayList<Menu>();

		List<WxMenu> root = this.loadRootNode();
		for (WxMenu menu : root) {
			if(null != menu.getStatus() && menu.getStatus() == 1) {
				list.add(recursiveWeixinMenu(menu));
			}
		}
		return list;
	}
	
	private Menu recursiveWeixinMenu(WxMenu menu) {
		Menu wxMenu = new Menu() ;
		wxMenu.setName(menu.getName());
		wxMenu.setKey(menu.getEventKey());
		wxMenu.setType(menu.getType());
		wxMenu.setUrl(menu.getUrl());
		wxMenu.setAppid(menu.getAppid());
		wxMenu.setPagepath(menu.getPagepath());
		wxMenu.setMedia_id(menu.getMediaId());
		
		List<WxMenu> childs = this.mapper.loadChildrenNode(menu.getId());
		if (null != childs && childs.size() > 0) {
			List<Menu> sub_menus = new ArrayList<Menu>() ;
			for (WxMenu m : childs) {
				if(m.getStatus() == 1) {
					Menu wxm = new Menu() ;
					wxm.setName(m.getName());
					wxm.setKey(m.getEventKey());
					wxm.setType(m.getType());
					wxm.setUrl(m.getUrl());
					wxm.setAppid(menu.getAppid());
					wxm.setPagepath(menu.getPagepath());
					wxm.setMedia_id(menu.getMediaId());
					
					sub_menus.add(recursiveWeixinMenu(m));
				}
				
			}
			wxMenu.setSub_button(sub_menus);
		}
		return wxMenu;
	}
	
	@Override
	public WxMenu selectMenyByKey(String key) throws WxMenuBizException {
		return this.mapper.selectMenyByKey(key) ;
	}
	

	@Override
	public Long clearCache() {
		Long delKeys = this.jedisClient.delKeys(RedisNamespace.WX_MENU_LIST, RedisNamespace.WX_MENU_TREE, RedisNamespace.WX_MENU_TREE_CHILDREN, RedisNamespace.WX_MENU_TREE_ROOT, RedisNamespace.WX_MENU_TREEGRID);
		return delKeys;
	}

}
